﻿using System;
using System.ComponentModel;

namespace Gonte.Reflection
{
    /// <summary>
    /// Converts from one field to other
    /// </summary>
    public static class ObjectTypeConverter
    {
        /// <summary>
        /// Converts a value to the appropriate field
        /// </summary>
        /// <param name="value">The value to set</param>
        /// <param name="field">The field to convert to</param>
        /// <returns>The converted object</returns>
        public static Object ConvertValue(Object value, Type type)
        {
            if (type.IsEnum == false)
            {
                if (type == typeof(Guid))
                {
                    return new Guid(value.ToString());
                }
                else if (TypeHelper.IsNullable(type))
                {
                    NullableConverter nullableConverter = new NullableConverter(type);
                    type = nullableConverter.UnderlyingType;

                    return Convert.ChangeType(value, type); // Use IConvertible
                }
                else
                {
                    return Convert.ChangeType(value, type); // Use IConvertible
                }
            }

            try
            {
                return Enum.ToObject(type, value); // Convert to an enumeration
            }
            catch
            {
                TypeConverter converter = TypeDescriptor.GetConverter(type);
                if (converter == null)
                {
                    throw new ArgumentNullException("Converter");
                }

                return Enum.ToObject(type, converter.ConvertFrom(value)); // Convert to an enumeration
            }
        }

        /// <summary>
        /// Converts a value to the appropriate field
        /// </summary>
        /// <typeparam name="T">The field to convert to</typeparam>
        /// <param name="value">The object to convert</param>
        /// <returns>The converted object</returns>
        public static T ConvertValue<T>(Object value)
        {
            return (T)ConvertValue(value, typeof(T));
        }
    }
}
